//
//  ViewController.m
//  TestBLE
//
//  Created by leeson zhong on 2021/4/27.
//

#import "ViewController.h"
#import <CoreBluetooth/CoreBluetooth.h>
#import "MBProgressHUD.h"

#define DEF_HEX @"1234567890abcdefABCDEF"

@interface ViewController ()<UITextViewDelegate,CBCentralManagerDelegate,CBPeripheralDelegate>{
    CBCentralManager *_mgr;
    //用于保存被发现设备
    NSMutableArray *peripherals;
    //用于保存设备名字，不用系统缓存的蓝牙名字
    NSMutableArray *bleNameArray;
    
    UIAlertController *waitAlert;
    
    BOOL *fourConnectState;
    
    NSMutableArray *fourWriteCharacteristicArray;
    
    CBPeripheral *fourConnectedPeripheral[4];
    
    NSMutableArray *fourConnectedName;
    
    int showPage;
}
@property (weak, nonatomic) IBOutlet UITextView *receiveDataTextView;
@property (weak, nonatomic) IBOutlet UITextView *sendDataTextView;
@property (weak, nonatomic) IBOutlet UIButton *ble1Button;
@property (weak, nonatomic) IBOutlet UIButton *ble2Button;
@property (weak, nonatomic) IBOutlet UIButton *ble3Button;
@property (weak, nonatomic) IBOutlet UIButton *ble4Button;
@property (weak, nonatomic) IBOutlet UIButton *connectButton;
@property (weak, nonatomic) IBOutlet UILabel *bleNameLabel;


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.receiveDataTextView.editable = false;
    self.sendDataTextView.delegate = self;
    
    //创建CBCentralManager对象
   dispatch_queue_t queue = dispatch_queue_create("bluetooth", DISPATCH_QUEUE_SERIAL);
   _mgr = [[CBCentralManager alloc] initWithDelegate:self queue:queue];
    
    peripherals = [[NSMutableArray alloc] init];
    bleNameArray = [[NSMutableArray alloc] init];
    
    fourWriteCharacteristicArray = [[NSMutableArray alloc] init];
    
    fourConnectState = malloc(sizeof(BOOL)*4);
    fourConnectedName = [[NSMutableArray alloc] init];
    for (int i=0; i<4; i++) {
        fourConnectState[i] = NO;
        NSMutableArray *arr = [[NSMutableArray alloc] init];
        [fourWriteCharacteristicArray addObject:arr];
        [fourConnectedName addObject:@""];
    }
    self.bleNameLabel.text = @"";
    
    showPage = 0;
}

//限制只能输入十六进制的数字和字符
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    //点击return退出键盘
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    
    NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:DEF_HEX]invertedSet];
    NSString *filtered = [[text componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""];
    BOOL basicTest = [text isEqualToString:filtered];
    if(!basicTest){
        return NO;
    }
    return YES;
}

- (IBAction)touchUpBleButton:(id)sender {
    UIButton *button = (UIButton *)sender;
    showPage = button.tag;
    self.receiveDataTextView.text = @"";
    self.bleNameLabel.text = [fourConnectedName objectAtIndex:showPage];
    if (fourConnectState[showPage]) {
        [self.connectButton setTitle:@"断开连接" forState:UIControlStateNormal];
    }else{
        [self.connectButton setTitle:@"连接蓝牙" forState:UIControlStateNormal];
    }
    switch (button.tag) {
        case 0:
            self.ble1Button.selected = YES;
            self.ble2Button.selected = NO;
            self.ble3Button.selected = NO;
            self.ble4Button.selected = NO;
            break;
        case 1:
            self.ble1Button.selected = NO;
            self.ble2Button.selected = YES;
            self.ble3Button.selected = NO;
            self.ble4Button.selected = NO;
            break;
        case 2:
            self.ble1Button.selected = NO;
            self.ble2Button.selected = NO;
            self.ble3Button.selected = YES;
            self.ble4Button.selected = NO;
            break;
        case 3:
            self.ble1Button.selected = NO;
            self.ble2Button.selected = NO;
            self.ble3Button.selected = NO;
            self.ble4Button.selected = YES;
            break;
            
        default:
            break;
    }
}

- (IBAction)touchUpConnectButton:(id)sender {
    [self showWaitDialog];
    if (fourConnectState[showPage]) {
        [_mgr cancelPeripheralConnection:fourConnectedPeripheral[showPage]];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self->waitAlert dismissViewControllerAnimated:YES completion:nil];
        });
    }else{
        [peripherals removeAllObjects];
        [bleNameArray removeAllObjects];
        //CBCentralManagerScanOptionAllowDuplicatesKey值为 No，表示不重复扫描已发现的设备
        NSDictionary *optionDic = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
        [_mgr scanForPeripheralsWithServices:nil options:optionDic];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self->_mgr stopScan];
            [self->waitAlert dismissViewControllerAnimated:YES completion:nil];
            [self showBleNameList];
        });
    }
}

- (IBAction)touchUpClearButton:(id)sender {
    self.receiveDataTextView.text = @"";
}

- (IBAction)touchUpSendButton:(id)sender {
    NSData *data = [self nsdataFromHexString:self.sendDataTextView.text];
    [self sendData:data];
}


//------------CBCentralManagerDelegate-----------------------------
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBManagerStatePoweredOn:
        {
            NSLog(@"开启蓝牙, 开始扫描");
        }
            break;
        case CBManagerStateUnsupported:
            NSLog(@"不支持蓝牙");
            break;
        case CBManagerStatePoweredOff:
            NSLog(@"蓝牙未打开");
            break;
            
        default:
            NSLog(@"蓝牙打开失败");
            break;
    }
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{
    if (peripheral.name != nil) {
        [peripherals addObject:peripheral];
        NSString *name = [advertisementData objectForKey:@"kCBAdvDataLocalName"];
        if (name) {
            [bleNameArray addObject:name];
        }else{
            [bleNameArray addObject:peripheral.name];
        }
        
    }
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    fourConnectState[showPage] = YES;
    [fourConnectedName replaceObjectAtIndex:showPage withObject:peripheral.name];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.connectButton setTitle:@"断开连接" forState:UIControlStateNormal];
        self.bleNameLabel.text = [NSString stringWithFormat:@"%@",peripheral.name];
    });
    peripheral.delegate = self;
    [peripheral discoverServices:nil];
    fourConnectedPeripheral[showPage]=peripheral;
    
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
    int index = 0;
    for (index=0; index<4; index++) {
        if ([fourConnectedPeripheral[index] isEqual:peripheral]) {
            break;
        }
    }
    fourConnectState[index] = NO;
    [fourConnectedName replaceObjectAtIndex:index withObject:@""];
    if (index == showPage) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.connectButton setTitle:@"连接蓝牙" forState:UIControlStateNormal];
            self.bleNameLabel.text = @"";
        });
    }
    
}

//-------------------------CBPeripheralDelegate---------------------------
//扫描到services
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
    if(error){
        NSLog(@"didDiscoverServices error");
        return;
    }
    for (CBService *service in peripheral.services) {
        //扫描每个service的characteristics
        [peripheral discoverCharacteristics:nil forService:service];
    }
}
//扫描到characteristics
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
    if(error){
        NSLog(@"didDiscoverCharacteristicsForService error");
        return;
    }
    int index = 0;
    for (index=0; index<4; index++) {
        if ([fourConnectedPeripheral[index] isEqual:peripheral]) {
            break;
        }
    }
    for (CBCharacteristic *characteristic in service.characteristics) {
    
        if (characteristic.properties & CBCharacteristicPropertyWrite) {
            NSMutableArray *writeCharacteristicArray = [fourWriteCharacteristicArray objectAtIndex:index];
            [writeCharacteristicArray addObject:characteristic];
            [fourWriteCharacteristicArray replaceObjectAtIndex:index withObject:writeCharacteristicArray];
        }
        if (characteristic.properties & CBCharacteristicPropertyNotify) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
    }
}
//获取到characteristics的数据
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
    NSData *data = characteristic.value;
    NSString *resultStr = [self hexStringFromNSdata:data];
    dispatch_async(dispatch_get_main_queue(), ^{
        //设置为 NO 后 UITextView 就不会再自己重置滑动
        self.receiveDataTextView.layoutManager.allowsNonContiguousLayout = NO;
        
        self.receiveDataTextView.text = [NSString stringWithFormat:@"%@\n%@",self.receiveDataTextView.text,resultStr];
        
        //每次添加内容后，将视图滚动到最后
        [self.receiveDataTextView scrollRangeToVisible:NSMakeRange(self.receiveDataTextView.text.length, 1)];
    });
}

-(void)showWaitDialog{
    if (!waitAlert) {
        waitAlert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Please wait...", nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIViewController *customVC = [[UIViewController alloc] init];
        UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [spinner startAnimating];
        [customVC.view addSubview:spinner];
        [customVC.view addConstraint:[NSLayoutConstraint constraintWithItem:spinner attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:customVC.view attribute:NSLayoutAttributeCenterX multiplier:1.0f constant:0.0f]];
        [customVC.view addConstraint:[NSLayoutConstraint constraintWithItem:spinner attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:customVC.view attribute:NSLayoutAttributeCenterY multiplier:1.0f constant:0.0f]];
        [waitAlert setValue:customVC forKey:@"contentViewController"];
    }
    [self presentViewController:waitAlert animated:YES completion:nil];
}

-(void)showBleNameList{
    //弹出表单框
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Select a bluetooth to connect", nil) message:nil preferredStyle:UIAlertControllerStyleAlert];
    for (int i=0; i<peripherals.count; i++) {
        CBPeripheral *peripheral = peripherals[i];
        NSString *bleName = peripheral.name;
        //NSString *bleName = bleNameArray[i];
        [alertController addAction:[UIAlertAction actionWithTitle:[NSString stringWithFormat:@"%@",bleName] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){
            //NSLog(@"选择第%d个",i);
            NSMutableArray *writeCharacteristicArray = [self->fourWriteCharacteristicArray objectAtIndex:self->showPage];
            [writeCharacteristicArray removeAllObjects];
            [self->fourWriteCharacteristicArray replaceObjectAtIndex:self->showPage withObject:writeCharacteristicArray];
            [self->_mgr connectPeripheral:peripheral options:nil];
        }]];
    }
    [alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){
        //NSLog(@"退出表单");
    }]];
    [self presentViewController:alertController animated:YES completion:nil];
}

- (void)sendData:(NSData *)data{
    NSMutableArray *writeCharacteristicArray = [fourWriteCharacteristicArray objectAtIndex:showPage];
    for (CBCharacteristic *characteristic in writeCharacteristicArray) {
        [fourConnectedPeripheral[showPage] writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
    }
}

-(NSString *)hexStringFromNSdata:(NSData *)data{
    Byte *byteData = (Byte *)[data bytes];
    NSString *hexString = @"";
    for (int i=0; i<data.length; i++) {
        hexString = [NSString stringWithFormat:@"%@%02X",hexString,byteData[i]];
    }
    return hexString;
}

-(NSData *)nsdataFromHexString:(NSString *)hexString{
    const char* ch = [[hexString lowercaseString] cStringUsingEncoding:NSUTF8StringEncoding];
    NSMutableData* data = [NSMutableData data];

    while (*ch) {
        if (*ch == ' ') {
            continue;
        }
        char byte = 0;
        if ('0' <= *ch && *ch <= '9') {
            byte = *ch - '0';
        }

        else if ('a' <= *ch && *ch <= 'f') {
            byte = *ch - 'a' + 10;
        }

        else if ('A' <= *ch && *ch <= 'F') {
            byte = *ch - 'A' + 10;
        }
        ch++;
        byte = byte << 4;
        if (*ch) {
            if ('0' <= *ch && *ch <= '9') {
                byte += *ch - '0';
            } else if ('a' <= *ch && *ch <= 'f') {
                byte += *ch - 'a' + 10;
            }

            else if('A' <= *ch && *ch <= 'F')
            {
                byte += *ch - 'A' + 10;
            }
            ch++;
        }
        [data appendBytes:&byte length:1];
    }
    return data;
}


@end
